#include "Exchange.hpp"
#include "MsgQueue.hpp"
#include "Binding.hpp"
#include "Messsage.hpp"

namespace mq
{
    class VirtualHost
    {
    public:
        using VirtualHostPtr = shared_ptr<VirtualHost>;
        VirtualHost(const string &hname, const string &basedir, const string &dbfile)
            : _host_name(hname),
              _emp(make_shared<ExchangeManager>(dbfile)),
              _mqmp(make_shared<MsgQueueManager>(dbfile)),
              _bmp(make_shared<BindingManager>(dbfile)),
              _mmp(make_shared<MessageManager>(basedir))
        {
            MsgQueueManager::QueueMap queues = _mqmp->allQueues();
            for (auto &q : queues)
                _mmp->initQueueMessage(q.first);
        }
        // 新建一个交换机
        bool declareExchange(const string &name, ExchangeType type, bool durable, bool auto_delete,
                             const google::protobuf::Map<string, string> &args)
        {
            return _emp->declareExchange(name, type, durable, auto_delete, args);
        }
        // 删除特定交换机
        void deleteExchange(const string &name)
        {
            _bmp->removeExchangeBindings(name);
            return _emp->deleteExchange(name);
        }
        // 判断交换机是否存在
        bool existsExchange(const string &name)
        {
            return _emp->exists(name);
        }
        // 查找特定交换机
        Exchange::ExchangePtr selectExchange(const string &ename)
        {
            return _emp->selectExchange(ename);
        }
        // 新建一个队列
        bool declareQueue(const string &name, bool durable, bool exclusive, bool auto_delete,
                          const google::protobuf::Map<string, string> &args)
        {
            _mmp->initQueueMessage(name);
            return _mqmp->declareQueue(name, durable, exclusive, auto_delete, args);
        }
        // 删除特定队列
        void deleteQueue(const string &name)
        {
            _bmp->removeMsgQueueBindings(name);
            _mqmp->deleteQueue(name);
        }
        // 判断队列是否存在
        bool existsQueue(const string &name)
        {
            return _mqmp->exists(name);
        }
        // 添加绑定关系
        bool Bind(const string &ename, const string &qname, const string &key)
        {
            Exchange::ExchangePtr ep = _emp->selectExchange(ename);
            if (ep.get() == nullptr)
            {
                DLOG("不存在目标交换机: %s", ename.c_str());
                return false;
            }
            MsgQueue::MsgQueuePtr mp = _mqmp->selectQueue(qname);
            if (ep.get() == nullptr)
            {
                DLOG("不存在目标队列: %s", qname.c_str());
                return false;
            }
            return _bmp->bind(ename, qname, key, ep->_durable && mp->_durable);
        }
        // 删除绑定关系
        void unBind(const string &ename, const string &qname)
        {
            return _bmp->unBind(ename, qname);
        }
        // 获取指定交换机中所有绑定关系（队列--->绑定关系）
        BindingManager::MsgQueueBindingMap exchangeBindings(const string &ename)
        {
            return _bmp->getExchangeBindings(ename);
        }
        // 判断指定绑定关系是否存在
        bool existsBinding(const string &ename, const string &qname)
        {
            return _bmp->exists(ename, qname);
        }
        // 向指定队列发布一条消息
        bool basicPublish(const string &qname, BasicProperties *bp, const string &body)
        {
            MsgQueue::MsgQueuePtr mqp = _mqmp->selectQueue(qname);
            if (mqp.get() == nullptr)
            {
                DLOG("不存在目标队列:%s", qname.c_str());
                return false;
            }
            // DLOG("%s -> %s", qname.c_str(), body.c_str());
            return _mmp->insert(qname, bp, body, mqp->_durable);
        }
        // 从指定队列中消费一条消息
        MessageManager::MessagePtr basicConsume(const string &qname)
        {
            return _mmp->front(qname);
        }
        // 向指定队列中确认一条消息
        void basicAck(const string &qname, const string &msg_id)
        {
            _mmp->ack(qname, msg_id);
        }
        // 清空虚拟机中所有内容
        void clear()
        {
            _emp->clear();
            _mqmp->clear();
            _bmp->clear();
            _mmp->clear();
        }
        MsgQueueManager::QueueMap allqueue()
        {
            return _mqmp->allQueues();
        }

    private:
        string _host_name;
        ExchangeManager::ExchangeManagerPtr _emp;  // 交换机管理操作句柄
        MsgQueueManager::MsgQueueManagerPtr _mqmp; // 队列管理操作句柄
        BindingManager::BindingManagerPtr _bmp;    // 绑定管理操作句柄
        MessageManager::MessageManagerPtr _mmp;    // 消息管理（队列）操作句柄
    };
}
